package org.zjx.analysis.analyze;

import java.awt.image.BufferedImage;
import java.util.*;
import java.util.concurrent.*;

/**
 * 高效分析管理器 - 分离判断和分析
 */
public class DefaultAnalysisManager implements AnalysisManager {

    private final List<ImageAnalyzer> analyzers;
    private final Map<String, ImageAnalyzer> analyzerMap;
    private final ExecutorService matchExecutor;

    public DefaultAnalysisManager() {
        this.analyzers = new CopyOnWriteArrayList<>();
        this.analyzerMap = new ConcurrentHashMap<>();

        // 创建专用的匹配线程池
        int poolSize = Math.max(2, Runtime.getRuntime().availableProcessors());
        this.matchExecutor = Executors.newFixedThreadPool(poolSize, r -> {
            Thread t = new Thread(r, "analyzer-matcher");
            t.setDaemon(true);
            return t;
        });
    }

    @Override
    public void registerAnalyzer(ImageAnalyzer analyzer) {
        Objects.requireNonNull(analyzer, "分析器不能为null");

        String analyzerName = analyzer.getAnalyzerName();
        if (analyzerMap.containsKey(analyzerName)) {
            throw new IllegalArgumentException("分析器已存在: " + analyzerName);
        }

        analyzers.add(analyzer);
        analyzerMap.put(analyzerName, analyzer);

        System.out.println("注册分析器: " + analyzerName + " [场景: " + analyzer.getSceneType() + "]");
    }

    @Override
    public void unregisterAnalyzer(String analyzerName) {
        ImageAnalyzer analyzer = analyzerMap.remove(analyzerName);
        if (analyzer != null) {
            analyzers.remove(analyzer);
            System.out.println("注销分析器: " + analyzerName);
        }
    }

    @Override
    public List<ImageAnalyzer> getAnalyzers() {
        return new ArrayList<>(analyzers);
    }

    @Override
    public Optional<ImageAnalyzer> findMatchedAnalyzer(BufferedImage image) {
        if (image == null || analyzers.isEmpty()) {
            return Optional.empty();
        }

        long startTime = System.currentTimeMillis();

        try {
            // 多线程并行查找第一个匹配的分析器
            Optional<ImageAnalyzer> matchedAnalyzer = findFirstMatchParallel(image);

            if (matchedAnalyzer.isPresent()) {
                ImageAnalyzer analyzer = matchedAnalyzer.get();
                System.out.println("匹配到分析器: " + analyzer.getAnalyzerName() +
                        " [耗时: " + (System.currentTimeMillis() - startTime) + "ms]");
            } else {
                System.out.println("未匹配到分析器 [耗时: " + (System.currentTimeMillis() - startTime) + "ms]");
            }

            return matchedAnalyzer;

        } catch (Exception e) {
            System.err.println("匹配过程异常: " + e.getMessage());
            return Optional.empty();
        }
    }

    /**
     * 多线程并行查找第一个匹配的分析器
     */
    private Optional<ImageAnalyzer> findFirstMatchParallel(BufferedImage image) {
        if (analyzers.size() == 1) {
            // 只有一个分析器时直接检查
            ImageAnalyzer analyzer = analyzers.get(0);
            return analyzer.matches(image) ? Optional.of(analyzer) : Optional.empty();
        }

        // 使用CompletableFuture.anyOf查找第一个匹配的分析器
        @SuppressWarnings("unchecked")
        CompletableFuture<Optional<ImageAnalyzer>>[] futures = analyzers.stream()
                .map(analyzer -> createMatchFuture(analyzer, copy(image)))
                .toArray(CompletableFuture[]::new);

        try {
            // 等待第一个匹配的结果
            CompletableFuture<Object> firstCompleted = CompletableFuture.anyOf(futures);

            // 设置超时时间
            Object result = firstCompleted.get(3, TimeUnit.SECONDS); // 1秒超时

            @SuppressWarnings("unchecked")
            Optional<ImageAnalyzer> matchedAnalyzer = (Optional<ImageAnalyzer>) result;

            if (matchedAnalyzer.isPresent()) {
                // 找到匹配的分析器，取消其他任务
                cancelAllFutures(futures);
                return matchedAnalyzer;
            }

            // 如果第一个完成的是空结果，检查其他可能的结果
            return checkOtherResults(futures);

        } catch (TimeoutException e) {
            System.err.println("匹配超时，取消所有任务");
            cancelAllFutures(futures);
            return Optional.empty();
        } catch (Exception e) {
            System.err.println("并行匹配异常: " + e.getMessage());
            return Optional.empty();
        }
    }

    /**
     * 为单个分析器创建匹配检查任务
     */
    private CompletableFuture<Optional<ImageAnalyzer>> createMatchFuture(ImageAnalyzer analyzer, BufferedImage image) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                return analyzer.matches(image) ? Optional.of(analyzer) : Optional.<ImageAnalyzer>empty();
            } catch (Exception e) {
                System.err.println("分析器匹配检查异常 [" + analyzer.getAnalyzerName() + "]: " + e.getMessage());
                return Optional.empty();
            }
        }, matchExecutor);
    }

    /**
     * 检查其他可能的结果
     */
    private Optional<ImageAnalyzer> checkOtherResults(CompletableFuture<Optional<ImageAnalyzer>>[] futures) {
        for (CompletableFuture<Optional<ImageAnalyzer>> future : futures) {
            if (future.isDone() && !future.isCompletedExceptionally()) {
                try {
                    Optional<ImageAnalyzer> result = future.get();
                    if (result.isPresent()) {
                        return result;
                    }
                } catch (Exception e) {
                    // 忽略异常，继续检查下一个
                }
            }
        }
        return Optional.empty();
    }

    /**
     * 取消所有未完成的任务
     */
    private void cancelAllFutures(CompletableFuture<?>[] futures) {
        for (CompletableFuture<?> future : futures) {
            if (!future.isDone()) {
                future.cancel(true);
            }
        }
    }

    private BufferedImage copy(BufferedImage screenshot) {
        // 创建副本，以避免对原图像产生影响
        BufferedImage copy = new BufferedImage(screenshot.getWidth(), screenshot.getHeight(), BufferedImage.TYPE_INT_ARGB);
        copy.getGraphics().drawImage(screenshot, 0, 0, null);
        return copy;
    }

    /**
     * 关闭线程池
     */
    public void shutdown() {
        matchExecutor.shutdown();
    }
}